/*
 * GLaDOS
 * Proteus5 GUI Application
 */

package proteus5gui;
import java.io.*;
import java.net.*;
import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.TaskMonitor;
import de.hardcode.jxinput.*;

import java.awt.*;
import java.awt.event.*;
import java.util.Vector;

import javax.media.*;
import javax.media.rtp.*;
import javax.media.rtp.event.*;
import javax.media.control.BufferControl;


import javax.media.protocol.DataSource;
import javax.swing.*;




/**
 * The application's main frame.
 */
public class Proteus5GUIView extends FrameView{

    boolean manualMode = true;

    boolean breakState = false;

    //define joystick calibration values and initialize
    JXInputDevice joystick = JXInputManager.getJXInputDevice(0);
    int breakButtonIndex = 0; //index of joystick button to be pushed for breaking
    int joyValXMid = 0;
    int joyValXRange = 200;
    int joyValYMid = 0;
    int joyValYRange = 200;
    int joyValX = 0; //raw joystick values
    int joyValY = 0;
    int joyOutputX = 0; //raw joystick values converted to percentages based on user inputed calibration values
    int joyOutputY = 0;
    int motorLeft = 0; //motor values range from -255 to 255.
    int motorRight = 0;
    boolean joyError = false;//set to true if joystick is detected

    //autonomous vars
    autonomousMode auto = null;
    Thread autoThread = null;

    //server vars
    String serverName = "mikelp";
    boolean connected = false;
    Socket serverSocket = null;
    PrintWriter out = null;
    BufferedReader in = null;
    String[] argv = new String[1];
    AVReceive2 video = null;
    Thread T = null;

    int consoleMsgNum = 0; //this increments every time a message is shown.  This number is displayed before each message in consoleBox


    //updates the user console (box above the video stream in the GUI)
    public void updateConsole(String msg, int color)  //color-> 0=red 1=yellow 2=green
    {
         
         consoleMsgNum++;

          switch(color){
             case 0:
                 consoleBox.setForeground(Color.red);
                 break;

             case 1:
                 consoleBox.setForeground(Color.yellow);
                 break;

             case 2:
                 consoleBox.setForeground(Color.green);
                 break;

             default:
                 consoleBox.setForeground(Color.red);
                 consoleBox.setText(Integer.toString(consoleMsgNum) + ". " + consoleBox.getText() + "0 1 and 2 and the only acceptable ints for int color...\n");
                 break;

         }

         consoleBox.setText(consoleBox.getText() + Integer.toString(consoleMsgNum) + ". " + msg + "\n");

    }

    /*This access the joystick for user control of the robot*/
    /*called when the autonomous checkbox under "options" is unchecked*/
    public void joyStickControl() {
        //This method updates DXinput values
        JXInputManager.updateFeatures();

        try
        {
            //Get joystick value and change domain from +-1 to +-100
             joyValX = (int)(-100*joystick.getAxis(0).getValue());
             joyValY = (int)(-100*joystick.getAxis(1).getValue());

        } catch (NullPointerException np){
             if (joyError == false)  //this ensures the joystick error msg is only displayed once.  Otherwise it will continually update overwriting other errors.
             {
                  joyError = true;
                  updateConsole("No joystick found - Add joystick in \"Game Controllers\" in Control Panel and restart GUI.", 0);
             }

        }





        if (joyError == false)
        {
            /****************************************************************/
            /*******************Parse joystick data**************************/
            /****************************************************************/


            joyOutputX = (200/joyValXRange)*(joyValX - joyValXMid); //convert joy values to percentage based on user inputed calibration values
            joyOutputY = (200/joyValYRange)*(joyValY - joyValYMid);


            motorRight = (255/100)*(joyOutputY + joyOutputX);//parse motor PWM Values from calibrated joystick values
            motorLeft = (255/100)*(joyOutputY - joyOutputX);//joystick(100 to -100)-> pwm(255 to -255) f(x)=2.55x
            if (motorRight > 255)  //prevent going outside the -255 to 255 domain
                motorRight = 255;
            if (motorRight < -255)
                motorRight = -255;

            if (motorLeft > 255)
                motorLeft = 255;
            if (motorLeft < -255)
                motorLeft = -255;


            breakState = joystick.getButton(breakButtonIndex).getState();
                
        }
    }

    class autonomousMode {
        public void autonomousMode() {

        }


        public void run() {
            /*autonomous code goes here*/

            //this code is here purely as an example of the autonomous framework.
            //New code should be written when proteus' sensor packaged is finalized
            setMotorLeft(100);
            setMotorRight(-100);
        }

        public void setMotorLeft(int percentLoad) {
            motorLeft = (255/100)*percentLoad; //PWM needs +-255 so adjust +-100 to PWM values
        }

        
        public void setMotorRight(int percentLoad) {
            motorRight = (255/100)*percentLoad;
        }

        public void wait(int miliSeconds){

        }

    }


       
    public Proteus5GUIView(SingleFrameApplication app) {
        super(app);

        initComponents();

        this.getFrame().setResizable(false); //stop the window resize event.  Window resize stops video repaint event

        ButtonGroup group = new ButtonGroup(); //put joystick button menu items into a group.
        group.add(jRadioJoyButton1);
        group.add(jRadioJoyButton2);
        group.add(jRadioJoyButton3);
        group.add(jRadioJoyButton4);
        group.add(jRadioJoyButton5);

        //only enable menu items associated with a joystick button at the same index
        int numberOfButtons = joystick.getNumberOfButtons();
        if (numberOfButtons >= 1) {
            jRadioJoyButton1.setEnabled(true);
        }
        if (numberOfButtons >= 2) {
            jRadioJoyButton2.setEnabled(true);
        }
        if (numberOfButtons >= 3) {
            jRadioJoyButton3.setEnabled(true);
        }
        if (numberOfButtons >= 4) {
            jRadioJoyButton4.setEnabled(true);
        }
        if (numberOfButtons >= 5) {
            jRadioJoyButton5.setEnabled(true);
        }

        //TO-DO preliminary code to detect multiple joysticks and have user select appropriate one
        //int numberOfDevices = de.hardcode.jxinput.JXInputManager.getNumberOfDevices();
        //System.out.println(numberOfDevices);

       /* for (int i=0;i<(numberOfDevices - 1);i++) {
            JXInputDevice joystick = JXInputManager.getJXInputDevice(i);

        }*/


       serverNameTextBox.setText(serverName);//initialize server name textbox
       connectButton.setForeground(Color.green); //initialize connect button colors

       heartBeatTimer = new Timer(1, new ActionListener(){



                public void actionPerformed(ActionEvent e) {
                /*Add timer relevant code here*/
                if (manualMode == true)
                    joyStickControl();
                else if (manualMode == false) {
                    auto.run();
                }

                
                joySliderY.setValue((100*(motorLeft + motorRight))/255);  //I'm recalculating these values so these .setValue statements work for both manual ant auto modes
                joySliderX.setValue((100*(motorRight - motorLeft))/255);
                motorSliderLeft.setValue(motorLeft);
                motorSliderRight.setValue(motorRight);
                
                if (connected == true){
                    Color breakLabelColor = null;
                    if (breakState == true) {
                         out.println(Integer.toString(motorLeft) + "," + Integer.toString(motorRight) + "," + "1");
                         breakLabelColor = new Color(255,0,0);
                    }
                    else {
                        out.println(Integer.toString(motorLeft) + "," + Integer.toString(motorRight) + "," + "0");
                        breakLabelColor = new Color(36,43,57);
                    }
                    breakLabel.setForeground(breakLabelColor);
                }

                int leftMotorTemp = motorLeft; //store motor values in temp variables so we can adjust the values without effecting the values
                int rightMotorTemp = motorRight;
                Color leftMotorColor;
                Color rightMotorColor;

                if (leftMotorTemp < 0)  //eliminate negetive values (rgb values must be between 0 and 255)
                    leftMotorTemp = -1*leftMotorTemp;

                if (leftMotorTemp >= 43) //this starts adding green after 43 to add the transparency effect near 0% load
                    leftMotorColor = new Color(36,leftMotorTemp,57);
                else
                    leftMotorColor = new Color(36,43,57);


                if (rightMotorTemp < 0)
                    rightMotorTemp = -1*rightMotorTemp;

                if (rightMotorTemp >= 43)
                    rightMotorColor = new Color(36,rightMotorTemp,57);
                else
                    rightMotorColor = new Color(36,43,57);


                motorSliderLeft.setBackground(leftMotorColor); //set backround of sliders to determined values
                motorSliderRight.setBackground(rightMotorColor);
                
                
            }
        });

        /**********************************************************************/
        /**********************Timer stuff - don't mess with this**************/
        /**********************************************************************/
        heartBeatTimer.start();

        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                statusMessageLabel.setText("");
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        });
        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
        statusAnimationLabel.setIcon(idleIcon);
        progressBar.setVisible(false);

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        statusAnimationLabel.setIcon(busyIcons[0]);
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(true);
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                    statusAnimationLabel.setIcon(idleIcon);
                    progressBar.setVisible(false);
                    progressBar.setValue(0);
                } else if ("message".equals(propertyName)) {
                    String text = (String)(evt.getNewValue());
                    statusMessageLabel.setText((text == null) ? "" : text);
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer)(evt.getNewValue());
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(value);
                }
            }
        });
    }

    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = Proteus5GUIApp.getApplication().getMainFrame();
            aboutBox = new Proteus5GUIAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        Proteus5GUIApp.getApplication().show(aboutBox);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        connectButton = new javax.swing.JButton();
        joySliderX = new javax.swing.JSlider();
        joySliderY = new javax.swing.JSlider();
        motorSliderLeft = new javax.swing.JSlider();
        motorSliderRight = new javax.swing.JSlider();
        motorLoadPositionLabel5 = new javax.swing.JLabel();
        motorLoadPositionLabel3 = new javax.swing.JLabel();
        motorLoadPositionLabel1 = new javax.swing.JLabel();
        motorLoadPositionLabel2 = new javax.swing.JLabel();
        motorLoadPositionLabel4 = new javax.swing.JLabel();
        jLabel12 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        consoleBox = new javax.swing.JTextArea();
        serverNameTextBox = new javax.swing.JTextField();
        videoPanel = new javax.swing.JPanel();
        jScrollPane3 = new javax.swing.JScrollPane();
        videoBackround = new javax.swing.JTextArea();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        serverPassword = new javax.swing.JPasswordField();
        breakLabel = new javax.swing.JLabel();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        autonomousCheckbox = new javax.swing.JMenu();
        joystickMenu = new javax.swing.JMenu();
        joystickCalibrate = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        jRadioJoyButton1 = new javax.swing.JRadioButtonMenuItem();
        jRadioJoyButton2 = new javax.swing.JRadioButtonMenuItem();
        jRadioJoyButton3 = new javax.swing.JRadioButtonMenuItem();
        jRadioJoyButton4 = new javax.swing.JRadioButtonMenuItem();
        jRadioJoyButton5 = new javax.swing.JRadioButtonMenuItem();
        autonomousMenuCheckbox = new javax.swing.JCheckBoxMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
        statusMessageLabel = new javax.swing.JLabel();
        statusAnimationLabel = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(proteus5gui.Proteus5GUIApp.class).getContext().getResourceMap(Proteus5GUIView.class);
        mainPanel.setBackground(resourceMap.getColor("mainPanel.background")); // NOI18N
        mainPanel.setFont(resourceMap.getFont("mainPanel.font")); // NOI18N
        mainPanel.setMaximumSize(new java.awt.Dimension(700, 700));
        mainPanel.setMinimumSize(new java.awt.Dimension(0, 0));
        mainPanel.setName("mainPanel"); // NOI18N
        mainPanel.setPreferredSize(new java.awt.Dimension(700, 650));
        mainPanel.addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                mainPanelComponentResized(evt);
            }
        });

        connectButton.setFont(resourceMap.getFont("CONNECT_button.font")); // NOI18N
        connectButton.setText(resourceMap.getString("CONNECT_button.text")); // NOI18N
        connectButton.setBorder(javax.swing.BorderFactory.createCompoundBorder());
        connectButton.setName("CONNECT_button"); // NOI18N
        connectButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectButtonActionPerformed(evt);
            }
        });

        joySliderX.setBackground(resourceMap.getColor("joySliderX.background")); // NOI18N
        joySliderX.setMinimum(-100);
        joySliderX.setPaintTicks(true);
        joySliderX.setValue(0);
        joySliderX.setEnabled(false);
        joySliderX.setName("joySliderX"); // NOI18N

        joySliderY.setBackground(resourceMap.getColor("joySliderY.background")); // NOI18N
        joySliderY.setMinimum(-100);
        joySliderY.setOrientation(javax.swing.JSlider.VERTICAL);
        joySliderY.setPaintTicks(true);
        joySliderY.setValue(0);
        joySliderY.setEnabled(false);
        joySliderY.setName("joySliderY"); // NOI18N

        motorSliderLeft.setBackground(resourceMap.getColor("motorSliderLeft.background")); // NOI18N
        motorSliderLeft.setMaximum(255);
        motorSliderLeft.setMinimum(-255);
        motorSliderLeft.setOrientation(javax.swing.JSlider.VERTICAL);
        motorSliderLeft.setPaintTicks(true);
        motorSliderLeft.setValue(0);
        motorSliderLeft.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        motorSliderLeft.setEnabled(false);
        motorSliderLeft.setName("motorSliderLeft"); // NOI18N

        motorSliderRight.setBackground(resourceMap.getColor("motorSliderRight.background")); // NOI18N
        motorSliderRight.setForeground(resourceMap.getColor("motorSliderRight.foreground")); // NOI18N
        motorSliderRight.setMaximum(255);
        motorSliderRight.setMinimum(-255);
        motorSliderRight.setOrientation(javax.swing.JSlider.VERTICAL);
        motorSliderRight.setPaintTicks(true);
        motorSliderRight.setValue(0);
        motorSliderRight.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        motorSliderRight.setEnabled(false);
        motorSliderRight.setName("motorSliderRight"); // NOI18N

        motorLoadPositionLabel5.setForeground(resourceMap.getColor("motorLoadPositionLabel5.foreground")); // NOI18N
        motorLoadPositionLabel5.setText(resourceMap.getString("motorLoadPositionLabel5.text")); // NOI18N
        motorLoadPositionLabel5.setName("motorLoadPositionLabel5"); // NOI18N

        motorLoadPositionLabel3.setBackground(resourceMap.getColor("motorLoadPositionLabel3.background")); // NOI18N
        motorLoadPositionLabel3.setForeground(resourceMap.getColor("motorLoadPositionLabel3.foreground")); // NOI18N
        motorLoadPositionLabel3.setText(resourceMap.getString("motorLoadPositionLabel3.text")); // NOI18N
        motorLoadPositionLabel3.setName("motorLoadPositionLabel3"); // NOI18N

        motorLoadPositionLabel1.setForeground(resourceMap.getColor("motorLoadPositionLabel1.foreground")); // NOI18N
        motorLoadPositionLabel1.setText(resourceMap.getString("motorLoadPositionLabel1.text")); // NOI18N
        motorLoadPositionLabel1.setName("motorLoadPositionLabel1"); // NOI18N

        motorLoadPositionLabel2.setForeground(resourceMap.getColor("motorLoadPositionLabel2.foreground")); // NOI18N
        motorLoadPositionLabel2.setText(resourceMap.getString("motorLoadPositionLabel2.text")); // NOI18N
        motorLoadPositionLabel2.setName("motorLoadPositionLabel2"); // NOI18N

        motorLoadPositionLabel4.setForeground(resourceMap.getColor("motorLoadPositionLabel4.foreground")); // NOI18N
        motorLoadPositionLabel4.setText(resourceMap.getString("motorLoadPositionLabel4.text")); // NOI18N
        motorLoadPositionLabel4.setName("motorLoadPositionLabel4"); // NOI18N

        jLabel12.setName("jLabel12"); // NOI18N

        jScrollPane2.setName("jScrollPane2"); // NOI18N

        consoleBox.setBackground(resourceMap.getColor("consoleBox.background")); // NOI18N
        consoleBox.setColumns(20);
        consoleBox.setRows(5);
        consoleBox.setName("consoleBox"); // NOI18N
        jScrollPane2.setViewportView(consoleBox);

        serverNameTextBox.setName("serverNameTextBox"); // NOI18N

        videoPanel.setBackground(resourceMap.getColor("videoPanel.background")); // NOI18N
        videoPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        videoPanel.setForeground(resourceMap.getColor("videoPanel.foreground")); // NOI18N
        videoPanel.setName("videoPanel"); // NOI18N

        jScrollPane3.setName("jScrollPane3"); // NOI18N

        videoBackround.setBackground(resourceMap.getColor("videoBackround.background")); // NOI18N
        videoBackround.setColumns(20);
        videoBackround.setForeground(resourceMap.getColor("videoBackround.foreground")); // NOI18N
        videoBackround.setRows(5);
        videoBackround.setText(resourceMap.getString("videoBackround.text")); // NOI18N
        videoBackround.setEnabled(false);
        videoBackround.setName("videoBackround"); // NOI18N
        jScrollPane3.setViewportView(videoBackround);

        javax.swing.GroupLayout videoPanelLayout = new javax.swing.GroupLayout(videoPanel);
        videoPanel.setLayout(videoPanelLayout);
        videoPanelLayout.setHorizontalGroup(
            videoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 686, Short.MAX_VALUE)
            .addGroup(videoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(videoPanelLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 666, Short.MAX_VALUE)
                    .addContainerGap()))
        );
        videoPanelLayout.setVerticalGroup(
            videoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 466, Short.MAX_VALUE)
            .addGroup(videoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(videoPanelLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 444, Short.MAX_VALUE)
                    .addContainerGap()))
        );

        jLabel1.setBackground(resourceMap.getColor("jLabel1.background")); // NOI18N
        jLabel1.setForeground(resourceMap.getColor("jLabel1.foreground")); // NOI18N
        jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
        jLabel1.setName("jLabel1"); // NOI18N

        jLabel2.setBackground(resourceMap.getColor("jLabel2.background")); // NOI18N
        jLabel2.setFont(resourceMap.getFont("jLabel2.font")); // NOI18N
        jLabel2.setForeground(resourceMap.getColor("jLabel2.foreground")); // NOI18N
        jLabel2.setText(resourceMap.getString("jLabel2.text")); // NOI18N
        jLabel2.setName("jLabel2"); // NOI18N

        serverPassword.setText(resourceMap.getString("serverPassword.text")); // NOI18N
        serverPassword.setName("serverPassword"); // NOI18N

        breakLabel.setForeground(resourceMap.getColor("breakLabel.foreground")); // NOI18N
        breakLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        breakLabel.setText(resourceMap.getString("breakLabel.text")); // NOI18N
        breakLabel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        breakLabel.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        breakLabel.setName("breakLabel"); // NOI18N

        javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addGap(174, 174, 174)
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 690, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addGap(30, 30, 30)
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(mainPanelLayout.createSequentialGroup()
                                .addGap(22, 22, 22)
                                .addComponent(jLabel12))
                            .addGroup(mainPanelLayout.createSequentialGroup()
                                .addGap(34, 34, 34)
                                .addComponent(motorSliderLeft, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(6, 6, 6)
                                .addComponent(motorSliderRight, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(4, 4, 4)
                                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(motorLoadPositionLabel1)
                                    .addComponent(motorLoadPositionLabel2)
                                    .addComponent(motorLoadPositionLabel3)
                                    .addComponent(motorLoadPositionLabel4)
                                    .addComponent(motorLoadPositionLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)))
                            .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(serverNameTextBox, javax.swing.GroupLayout.PREFERRED_SIZE, 117, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(24, 24, 24)
                        .addComponent(videoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(1, 1, 1)
                        .addComponent(joySliderY, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addGap(30, 30, 30)
                        .addComponent(serverPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(24, 24, 24)
                        .addComponent(joySliderX, javax.swing.GroupLayout.PREFERRED_SIZE, 685, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addGap(30, 30, 30)
                        .addComponent(connectButton, javax.swing.GroupLayout.PREFERRED_SIZE, 115, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(343, 343, 343)
                        .addComponent(breakLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addGap(54, 54, 54))
        );
        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addGap(11, 11, 11)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(11, 11, 11)
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addComponent(jLabel12, javax.swing.GroupLayout.PREFERRED_SIZE, 13, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(6, 6, 6)
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(motorSliderLeft, javax.swing.GroupLayout.PREFERRED_SIZE, 337, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(motorSliderRight, javax.swing.GroupLayout.PREFERRED_SIZE, 337, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(mainPanelLayout.createSequentialGroup()
                                .addComponent(motorLoadPositionLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 17, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(67, 67, 67)
                                .addComponent(motorLoadPositionLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 12, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(67, 67, 67)
                                .addComponent(motorLoadPositionLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 15, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(59, 59, 59)
                                .addComponent(motorLoadPositionLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(69, 69, 69)
                                .addComponent(motorLoadPositionLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addGap(41, 41, 41)
                        .addComponent(jLabel1)
                        .addGap(6, 6, 6)
                        .addComponent(serverNameTextBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(10, 10, 10)
                        .addComponent(jLabel2))
                    .addComponent(videoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(joySliderY, javax.swing.GroupLayout.PREFERRED_SIZE, 468, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(2, 2, 2)
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addGap(3, 3, 3)
                        .addComponent(serverPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(joySliderX, javax.swing.GroupLayout.PREFERRED_SIZE, 15, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addGap(10, 10, 10)
                        .addComponent(connectButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(breakLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))))
        );

        menuBar.setName("menuBar"); // NOI18N

        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(proteus5gui.Proteus5GUIApp.class).getContext().getActionMap(Proteus5GUIView.class, this);
        exitMenuItem.setAction(actionMap.get("quit")); // NOI18N
        exitMenuItem.setName("exitMenuItem"); // NOI18N
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        autonomousCheckbox.setText(resourceMap.getString("autonomousCheckbox.text")); // NOI18N
        autonomousCheckbox.setName("autonomousCheckbox"); // NOI18N
        autonomousCheckbox.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                autonomousCheckboxStateChanged(evt);
            }
        });
        autonomousCheckbox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                autonomousCheckboxActionPerformed(evt);
            }
        });

        joystickMenu.setText(resourceMap.getString("joystickMenu.text")); // NOI18N
        joystickMenu.setName("joystickMenu"); // NOI18N

        joystickCalibrate.setIcon(resourceMap.getIcon("joystickCalibrate.icon")); // NOI18N
        joystickCalibrate.setText(resourceMap.getString("joystickCalibrate.text")); // NOI18N
        joystickCalibrate.setName("joystickCalibrate"); // NOI18N
        joystickCalibrate.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                joystickCalibrateActionPerformed(evt);
            }
        });
        joystickMenu.add(joystickCalibrate);

        jSeparator1.setName("jSeparator1"); // NOI18N
        joystickMenu.add(jSeparator1);

        jRadioJoyButton1.setSelected(true);
        jRadioJoyButton1.setText(resourceMap.getString("jRadioJoyButton1.text")); // NOI18N
        jRadioJoyButton1.setEnabled(false);
        jRadioJoyButton1.setName("jRadioJoyButton1"); // NOI18N
        jRadioJoyButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioJoyButton1ActionPerformed(evt);
            }
        });
        joystickMenu.add(jRadioJoyButton1);

        jRadioJoyButton2.setText(resourceMap.getString("jRadioJoyButton2.text")); // NOI18N
        jRadioJoyButton2.setEnabled(false);
        jRadioJoyButton2.setName("jRadioJoyButton2"); // NOI18N
        jRadioJoyButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioJoyButton2ActionPerformed(evt);
            }
        });
        joystickMenu.add(jRadioJoyButton2);

        jRadioJoyButton3.setText(resourceMap.getString("jRadioJoyButton3.text")); // NOI18N
        jRadioJoyButton3.setEnabled(false);
        jRadioJoyButton3.setName("jRadioJoyButton3"); // NOI18N
        jRadioJoyButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioJoyButton3ActionPerformed(evt);
            }
        });
        joystickMenu.add(jRadioJoyButton3);

        jRadioJoyButton4.setText(resourceMap.getString("jRadioJoyButton4.text")); // NOI18N
        jRadioJoyButton4.setEnabled(false);
        jRadioJoyButton4.setName("jRadioJoyButton4"); // NOI18N
        jRadioJoyButton4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioJoyButton4ActionPerformed(evt);
            }
        });
        joystickMenu.add(jRadioJoyButton4);

        jRadioJoyButton5.setText(resourceMap.getString("jRadioJoyButton5.text")); // NOI18N
        jRadioJoyButton5.setEnabled(false);
        jRadioJoyButton5.setName("jRadioJoyButton5"); // NOI18N
        jRadioJoyButton5.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioJoyButton5ActionPerformed(evt);
            }
        });
        joystickMenu.add(jRadioJoyButton5);

        autonomousCheckbox.add(joystickMenu);

        autonomousMenuCheckbox.setText(resourceMap.getString("autonomousMenuCheckbox.text")); // NOI18N
        autonomousMenuCheckbox.setName("autonomousMenuCheckbox"); // NOI18N
        autonomousMenuCheckbox.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                autonomousMenuCheckboxStateChanged(evt);
            }
        });
        autonomousMenuCheckbox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                autonomousMenuCheckboxActionPerformed(evt);
            }
        });
        autonomousCheckbox.add(autonomousMenuCheckbox);

        menuBar.add(autonomousCheckbox);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        statusPanel.setName("statusPanel"); // NOI18N

        statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

        statusMessageLabel.setName("statusMessageLabel"); // NOI18N

        statusAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N

        progressBar.setName("progressBar"); // NOI18N

        javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(statusPanelSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 906, Short.MAX_VALUE)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(statusMessageLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 736, Short.MAX_VALUE)
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(statusAnimationLabel)
                .addContainerGap())
        );
        statusPanelLayout.setVerticalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addComponent(statusPanelSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(statusMessageLabel)
                    .addComponent(statusAnimationLabel)
                    .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(3, 3, 3))
        );

        setComponent(mainPanel);
        setMenuBar(menuBar);
        setStatusBar(statusPanel);
    }// </editor-fold>//GEN-END:initComponents

    private void text_XMidKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_text_XMidKeyPressed
        

    }//GEN-LAST:event_text_XMidKeyPressed

    private void text_YMidKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_text_YMidKeyPressed

    }//GEN-LAST:event_text_YMidKeyPressed

    private void connectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectButtonActionPerformed
        
        if (connected == false)
        {
            serverName = serverNameTextBox.getText(); //get server name from textbox
            try {
                serverSocket = new Socket(serverName, 4444);
                out = new PrintWriter(serverSocket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));

                
                //read the password from the password field
                char[] tempCharPassword = serverPassword.getPassword();
                //reset password field
                serverPassword.setText("000000000000000000");
                //at P: to the front of the password
                String tempStringPassword = "P:" + String.valueOf(tempCharPassword);
                //string to char[] and output to server
                char[] password = tempStringPassword.toCharArray();
                out.println(password);
                
                
                boolean connectionAccepted = false;
                boolean exitLoop = false;
                long currentTime = System.currentTimeMillis();
                long startTime = System.currentTimeMillis();
                String passwordResponse = null;

                do {
                    passwordResponse = in.readLine();
    
                   currentTime = System.currentTimeMillis();

                   System.out.println(passwordResponse);

                   if (passwordResponse == null){ //if no responce check how long its been
                         if ((currentTime - startTime) >= 5000){ //exit loop if longer than 5 seconds has elapsed
                            exitLoop = true;
                            updateConsole("Connection timeout", 0); //update console with msg
                        }
                   }
                   else if(passwordResponse.equals("P:1")) { //1 means the server accepted the connection
                       connectionAccepted = true;
                       updateConsole("Connection sucessfull", 2); //update console with msg
                       exitLoop = true;
                   }
                   else if(passwordResponse.equals("P:0")) { //0 means connection rejected-bad pass
                        connectionAccepted = false;
                        updateConsole("Connection rejected: Bad password", 0); //update console with msg
                        exitLoop = true;
                   }
                       
                       
                } while (exitLoop == false);
                    
                if (connectionAccepted == true){
                    argv[0] = serverSocket.getInetAddress().getHostAddress() + "/22222"; //IP and port to recieve RTP stream

                    videoBackround.setText("\n\n\n\n\n\n\n\n\n\n\n			         Waiting for RTP Stream");


                    video = new AVReceive2(argv);


                    T = new Thread(video);
                    T.start();


                    connected = true;
                    connectButton.setBackground(Color.green); //reformat into disconnect button
                    connectButton.setForeground(Color.red);
                    connectButton.setText("Disconnect");
                }

                
    
            } catch (UnknownHostException e) {
                updateConsole(("Cannot find host: " + serverName), 0); //update console with msg
            } catch (IOException e) {
                updateConsole(("Couldn't get I/O for the connection to: " + serverName), 0); //update console with msg
            }
        }
        else
        {
            try
            {
                //avReceive.close();
                out.close();
                in.close();
                serverSocket.close();

                video.close();

                videoBackround.setVisible(true);
                videoBackround.setText("\n\n\n\n\n\n\n\n\n\n\n			         No RTP Stream");

                connectButton.setBackground(Color.red);//reformat into connect button
                connectButton.setForeground(Color.green);
                connectButton.setText("Connect");
                connected = false;
            } catch(IOException e) {
                updateConsole(("IOException " + e.getMessage() + " to: " + serverName), 0); //update console with msg
            } catch (NullPointerException e) {
                updateConsole(("NullPointerExcpetion " + e.getMessage() + " to: " + serverName), 0); //update console with msg
            }
        }
    }//GEN-LAST:event_connectButtonActionPerformed

    private void mainPanelComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_mainPanelComponentResized


    }//GEN-LAST:event_mainPanelComponentResized

    private void joystickCalibrateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_joystickCalibrateActionPerformed
        // TODO add your handling code here:
        try {
            //open the windows game controller manager
            Process process = Runtime.getRuntime().exec(System.getenv("windir") +"\\system32\\"+"control.exe /joy.cpl");

        } catch(Exception e) {System.out.println(e.getMessage());}

    }//GEN-LAST:event_joystickCalibrateActionPerformed

    private void jRadioJoyButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioJoyButton1ActionPerformed
        // TODO add your handling code here:
        breakButtonIndex = 0;
    }//GEN-LAST:event_jRadioJoyButton1ActionPerformed

    private void jRadioJoyButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioJoyButton2ActionPerformed
        // TODO add your handling code here:
        breakButtonIndex = 1;
    }//GEN-LAST:event_jRadioJoyButton2ActionPerformed

    private void jRadioJoyButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioJoyButton3ActionPerformed
        // TODO add your handling code here:
        breakButtonIndex = 2;
    }//GEN-LAST:event_jRadioJoyButton3ActionPerformed

    private void jRadioJoyButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioJoyButton4ActionPerformed
        // TODO add your handling code here:
        breakButtonIndex = 3;
    }//GEN-LAST:event_jRadioJoyButton4ActionPerformed

    private void jRadioJoyButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioJoyButton5ActionPerformed
        // TODO add your handling code here:
        breakButtonIndex = 4;
    }//GEN-LAST:event_jRadioJoyButton5ActionPerformed

    private void autonomousCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_autonomousCheckboxActionPerformed
        // TODO add your handling code here:
  
    }//GEN-LAST:event_autonomousCheckboxActionPerformed

    private void autonomousCheckboxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_autonomousCheckboxStateChanged
        // TODO add your handling code here:
    }//GEN-LAST:event_autonomousCheckboxStateChanged

    private void autonomousMenuCheckboxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_autonomousMenuCheckboxStateChanged
        // TODO add your handling code here:

    }//GEN-LAST:event_autonomousMenuCheckboxStateChanged

    private void autonomousMenuCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_autonomousMenuCheckboxActionPerformed
        // TODO add your handling code here:
        if (manualMode == true){
            manualMode = false;
            auto = new autonomousMode();
        }
        else if (manualMode == false) {
            manualMode = true;
            auto = null;
        }
    }//GEN-LAST:event_autonomousMenuCheckboxActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenu autonomousCheckbox;
    private javax.swing.JCheckBoxMenuItem autonomousMenuCheckbox;
    private javax.swing.JLabel breakLabel;
    private javax.swing.JButton connectButton;
    private javax.swing.JTextArea consoleBox;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JRadioButtonMenuItem jRadioJoyButton1;
    private javax.swing.JRadioButtonMenuItem jRadioJoyButton2;
    private javax.swing.JRadioButtonMenuItem jRadioJoyButton3;
    private javax.swing.JRadioButtonMenuItem jRadioJoyButton4;
    private javax.swing.JRadioButtonMenuItem jRadioJoyButton5;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JSlider joySliderX;
    private javax.swing.JSlider joySliderY;
    private javax.swing.JMenuItem joystickCalibrate;
    private javax.swing.JMenu joystickMenu;
    public static javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JLabel motorLoadPositionLabel1;
    private javax.swing.JLabel motorLoadPositionLabel2;
    private javax.swing.JLabel motorLoadPositionLabel3;
    private javax.swing.JLabel motorLoadPositionLabel4;
    private javax.swing.JLabel motorLoadPositionLabel5;
    private javax.swing.JSlider motorSliderLeft;
    private javax.swing.JSlider motorSliderRight;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JTextField serverNameTextBox;
    private javax.swing.JPasswordField serverPassword;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JLabel statusMessageLabel;
    private javax.swing.JPanel statusPanel;
    public static javax.swing.JTextArea videoBackround;
    public static javax.swing.JPanel videoPanel;
    // End of variables declaration//GEN-END:variables

    private final Timer messageTimer;
    private final Timer busyIconTimer;
    private final Timer heartBeatTimer;
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;

    private JDialog aboutBox;
}

/**
 * AVReceive2 to receive RTP transmission using the new RTP API.
 */
class AVReceive2 implements ReceiveStreamListener, SessionListener,
	ControllerListener, Runnable
{
    String sessions[] = null;
    RTPManager mgrs[] = null;
    Vector playerWindows = null;
    DataSource ds = null;
    PlayerPanel video = null;

    boolean dataReceived = false;
    Object dataSync = new Object();

    public AVReceive2(String sessions[]) {
	this.sessions = sessions;
    }

    	public void run()
	{
              if (!initialize()) {
                    System.err.println("Failed to initialize the sessions.");
                    System.exit(-1);
               }

               try {
                    while (!isDone()) {
                        video.repaint();
                        Thread.sleep(1000);
                    }
               } catch (Exception e) {}
	}

        public void stop() {
            
            try{
                this.close(); 
            } catch (Exception e) {}
           
        }

    protected boolean initialize() {

        try {
	    InetAddress ipAddr;
	    SessionAddress localAddr = new SessionAddress();
	    SessionAddress destAddr;

	    mgrs = new RTPManager[sessions.length];
	    playerWindows = new Vector();

	    SessionLabel session;

	    // Open the RTP sessions.
	    for (int i = 0; i < sessions.length; i++) {

	 	// Parse the session addresses.
		try {
		    session = new SessionLabel(sessions[i]);
		} catch (IllegalArgumentException e) {
		    System.err.println("Failed to parse the session address given: " + sessions[i]);
		    return false;
		}

		System.err.println("  - Open RTP session for: addr: " + session.addr + " port: " + session.port + " ttl: " + session.ttl);

		mgrs[i] = (RTPManager) RTPManager.newInstance();
		mgrs[i].addSessionListener(this);
		mgrs[i].addReceiveStreamListener(this);

		ipAddr = InetAddress.getByName(session.addr);

		if( ipAddr.isMulticastAddress()) {
		    // local and remote address pairs are identical:
		    localAddr= new SessionAddress( ipAddr,
						   session.port,
						   session.ttl);
		    destAddr = new SessionAddress( ipAddr,
						   session.port,
						   session.ttl);
		} else {
		    localAddr= new SessionAddress( InetAddress.getLocalHost(),
			  		           session.port);
                    destAddr = new SessionAddress( ipAddr, session.port);
		}

		mgrs[i].initialize( localAddr);

		// You can try out some other buffer size to see
		// if you can get better smoothness.
		BufferControl bc = (BufferControl)mgrs[i].getControl("javax.media.control.BufferControl");
		if (bc != null)
		    bc.setBufferLength(350);

    		mgrs[i].addTarget(destAddr);

	    }

        } catch (Exception e){
            System.err.println("Cannot create the RTP Session: " + e.getMessage());
            return false;
        }

	// Wait for data to arrive before moving on.

	long then = System.currentTimeMillis();
	long waitingPeriod = 30000;  // wait for a maximum of 30 secs.

	try{
	    synchronized (dataSync) {
		while (!dataReceived &&
			System.currentTimeMillis() - then < waitingPeriod) {
		    if (!dataReceived){
                        System.err.println("  - Waiting for RTP data to arrive...");
                        Proteus5GUIView.videoBackround.setText(Proteus5GUIView.videoBackround.getText() + ".");
                    }
			
		    dataSync.wait(1000);
		}
	    }
	} catch (Exception e) {}

	if (!dataReceived) {
	    System.err.println("No RTP data was received.");
	    close();
	    return false;
	}

        return true;
    }


    public boolean isDone() {
	return playerWindows.size() == 0;
    }


    /**
     * Close the players and the session managers.
     */
    protected void close() {

        
	for (int i = 0; i < playerWindows.size(); i++) {
	    try {
		((PlayerWindow)playerWindows.elementAt(i)).close();
	    } catch (Exception e) {}
	}

	playerWindows.removeAllElements();

	// close the RTP session.
	for (int i = 0; i < mgrs.length; i++) {
	    if (mgrs[i] != null) {
                mgrs[i].removeTargets( "Closing session from AVReceive2");
                mgrs[i].dispose();
		mgrs[i] = null;
	    }
	}

        Proteus5GUIView.videoPanel.remove(video);

        
    }


    PlayerWindow find(Player p) {
	for (int i = 0; i < playerWindows.size(); i++) {
	    PlayerWindow pw = (PlayerWindow)playerWindows.elementAt(i);
	    if (pw.player == p)
		return pw;
	}
	return null;
    }


    PlayerWindow find(ReceiveStream strm) {
	for (int i = 0; i < playerWindows.size(); i++) {
	    PlayerWindow pw = (PlayerWindow)playerWindows.elementAt(i);
	    if (pw.stream == strm)
		return pw;
	}
	return null;
    }


    /**
     * SessionListener.
     */
    public synchronized void update(SessionEvent evt) {
	if (evt instanceof NewParticipantEvent) {
	    Participant p = ((NewParticipantEvent)evt).getParticipant();
	    System.err.println("  - A new participant had just joined: " + p.getCNAME());
	}
    }


    /**
     * ReceiveStreamListener
     */
    public synchronized void update( ReceiveStreamEvent evt) {

	RTPManager mgr = (RTPManager)evt.getSource();
	Participant participant = evt.getParticipant();	// could be null.
	ReceiveStream stream = evt.getReceiveStream();  // could be null.
        

	if (evt instanceof RemotePayloadChangeEvent) {

	    System.err.println("  - Received an RTP PayloadChangeEvent.");
	    System.err.println("Sorry, cannot handle payload change.");
	    System.exit(0);

	}

	else if (evt instanceof NewReceiveStreamEvent) {

	    try {
		stream = ((NewReceiveStreamEvent)evt).getReceiveStream();
		DataSource ds = stream.getDataSource();



 
		// Find out the formats.
		RTPControl ctl = (RTPControl)ds.getControl("javax.media.rtp.RTPControl");
		if (ctl != null){
		    System.err.println("  - Recevied new RTP stream: " + ctl.getFormat());
		} else
		    System.err.println("  - Recevied new RTP stream");

		if (participant == null)
		    System.err.println("      The sender of this stream had yet to be identified.");
		else {
		    System.err.println("      The stream comes from: " + participant.getCNAME());
		}

		// create a player by passing datasource to the Media Manager
		Player p = javax.media.Manager.createPlayer(ds);
		if (p == null)
		    return;

		p.addControllerListener(this);
		p.realize();
		PlayerWindow pw = new PlayerWindow(p, stream);


                //Manager.setHint(Manager.LIGHTWEIGHT_RENDERER, new Boolean(true));
		playerWindows.addElement(pw);

		// Notify intialize() that a new stream had arrived.
		synchronized (dataSync) {
		    dataReceived = true;
		    dataSync.notifyAll();
		}

	    } catch (Exception e) {
		System.err.println("NewReceiveStreamEvent exception " + e.getMessage());
		return;
	    }

	}

	else if (evt instanceof StreamMappedEvent) {

	     if (stream != null && stream.getDataSource() != null) {
		ds = stream.getDataSource();
		// Find out the formats.
		RTPControl ctl = (RTPControl)ds.getControl("javax.media.rtp.RTPControl");
		System.err.println("  - The previously unidentified stream ");
		if (ctl != null)
		    System.err.println("      " + ctl.getFormat());
		System.err.println("      had now been identified as sent by: " + participant.getCNAME());
	     }
	}

	else if (evt instanceof ByeEvent) {

	     System.err.println("  - Got \"bye\" from: " + participant.getCNAME());
	     PlayerWindow pw = find(stream);
	     if (pw != null) {
		pw.close();
		playerWindows.removeElement(pw);
	     }
	}

    }


    /**
     * ControllerListener for the Players.
     */
    public synchronized void controllerUpdate(ControllerEvent ce){

	Player p = (Player)ce.getSourceController();



	if (p == null)
	    return;

	// Get this when the internal players are realized.
	if (ce instanceof RealizeCompleteEvent) {
	    PlayerWindow pw = find(p);
	    if (pw == null) {
		// Some strange happened.
               
		System.err.println("Internal error!");
		System.exit(-1);
	    }
	    pw.initialize();
	    pw.setVisible(true);
	    p.start();
	}

	if (ce instanceof ControllerErrorEvent) {
	    p.removeControllerListener(this);
	    PlayerWindow pw = find(p);
	    if (pw != null) {
		pw.close();
		playerWindows.removeElement(pw);
	    }
	    System.err.println("AVReceive2 internal error: " + ce);
	}

    }


    /**
     * A utility class to parse the session addresses.
     */
    class SessionLabel {

	public String addr = null;
	public int port;
	public int ttl = 1;

	SessionLabel(String session) throws IllegalArgumentException {

	    int off;
	    String portStr = null, ttlStr = null;

	    if (session != null && session.length() > 0) {
		while (session.length() > 1 && session.charAt(0) == '/')
		    session = session.substring(1);

		// Now see if there's a addr specified.
		off = session.indexOf('/');
		if (off == -1) {
		    if (!session.equals(""))
			addr = session;
		} else {
		    addr = session.substring(0, off);
		    session = session.substring(off + 1);
		    // Now see if there's a port specified
		    off = session.indexOf('/');
		    if (off == -1) {
			if (!session.equals(""))
			    portStr = session;
		    } else {
			portStr = session.substring(0, off);
			session = session.substring(off + 1);
			// Now see if there's a ttl specified
			off = session.indexOf('/');
			if (off == -1) {
			    if (!session.equals(""))
				ttlStr = session;
			} else {
			    ttlStr = session.substring(0, off);
			}
		    }
		}
	    }

	    if (addr == null)
		throw new IllegalArgumentException();

	    if (portStr != null) {
		try {
		    Integer integer = Integer.valueOf(portStr);
		    if (integer != null)
			port = integer.intValue();
		} catch (Throwable t) {
		    throw new IllegalArgumentException();
		}
	    } else
		throw new IllegalArgumentException();

	    if (ttlStr != null) {
		try {
		    Integer integer = Integer.valueOf(ttlStr);
		    if (integer != null)
			ttl = integer.intValue();
		} catch (Throwable t) {
		    throw new IllegalArgumentException();
		}
	    }
	}
    }


    /**
     * GUI classes for the Player.
     */
    class PlayerWindow extends JPanel {

	Player player;
	ReceiveStream stream;

	PlayerWindow(Player p, ReceiveStream strm) {
	    player = p;
	    stream = strm;
	}


	public void initialize() {
            Manager.setHint(Manager.LIGHTWEIGHT_RENDERER, new Boolean(true));
            video = new PlayerPanel(player);
            video.setDoubleBuffered(true);
            Proteus5GUIView.videoBackround.setText("Waiting For RTP Stream");
            Proteus5GUIView.videoPanel.add(video);
            Proteus5GUIView.videoBackround.setText("");
            Proteus5GUIView.videoPanel.validate();
           
	}

	public void close() {
	    player.close();
	    setVisible(false);
	    //dispose();
	}

        @Override
	public void addNotify() {
	    super.addNotify();
	    //pack();
	}
    }


    /**
     * GUI classes for the Player.
     */
    class PlayerPanel extends JPanel {

	Component vc, cc;

	PlayerPanel(Player p) {
	    setLayout(new BorderLayout());
	    if ((vc = p.getVisualComponent()) != null)
            {
                vc.setSize(getPreferredSize());
                vc.setPreferredSize(getPreferredSize());
		add(vc);
                vc.setLocation(2,2);
            }
	    if ((cc = p.getControlPanelComponent()) != null)
		add(cc);
	}

        @Override
	public Dimension getPreferredSize() {
	    int w = 0, h = 0;
	
            w = Proteus5GUIView.videoPanel.getWidth() - 3;
            h = Proteus5GUIView.videoPanel.getHeight() - 3;
 
	    return new Dimension(w, h);
	}
    }


    static void prUsage() {
	System.err.println("Usage: AVReceive2 <session> <session> ...");
	System.err.println("     <session>: <address>/<port>/<ttl>");
	System.exit(0);
    }

}// end of AVReceive2
